package com.lxs.spring6.boot3.extend;

import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.HashMap;
import java.util.Map;


@Component
public class MyBeanNameAware implements BeanNameAware, InitializingBean {
    /**
     * Autowired 首先通过类型注入，类型匹配到多个则根据名称注入，通过名称没找到则抛错
     */
    @Autowired
    TestFactoryBean testFactoryBean;

    public MyBeanNameAware() {
        System.err.println("==========================【MyBeanNameAware】构造器执行");
    }

    /**
     * BeanNameAware: 这个类也是Aware扩展的一种，触发点在bean的初始化之前，也就是postProcessBeforeInitialization之前，这个类的触发点方法只有一个：setBeanName
     * 使用场景为：用户可以扩展这个点，在初始化该当前bean之前拿到spring容器中注册的的beanName，来自行修改这个beanName的值。
     */
    @Override
    public void setBeanName(String s) {
        System.err.println("【BeanNameAware.setBeanName】在初始化bean之前拿到spring容器中注册的的beanName: " + s);
    }

    /**
     * 这个并不算一个扩展点，其实就是一个标注。
     * 其作用是在bean的初始化阶段，如果对一个方法标注了@PostConstruct，会先调用这个方法。
     * 这里重点是要关注下这个标准的触发点，这个触发点是在postProcessBeforeInitialization之后，InitializingBean.afterPropertiesSet之前。
     * 使用场景：用户可以对某一方法进行标注，来进行初始化某一个属性
     */
    @PostConstruct
    public void init() {
        System.err.println("【@PostConstruct】：执行初始化方法。在postProcessBeforeInitialization之后，InitializingBean.afterPropertiesSet之前");
    }

    @PreDestroy
    public void preDestroy() {
        System.err.println("【@PreDestroy】：执行销毁方法");
    }

    /**
     * InitializingBean: 这个类，顾名思义，也是用来初始化bean的。
     * InitializingBean接口为bean提供了初始化方法的方式，它只包括afterPropertiesSet方法，凡是继承该接口的类，在初始化bean的时候都会执行该方法。
     * 这个扩展点的触发时机在postProcessAfterInitialization之前。
     * 使用场景：用户实现此接口，来进行系统启动的时候一些业务指标的初始化工作。
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        System.err.println("【InitializingBean-afterPropertiesSet】：postProcessAfterInitialization之前，进行系统启动的时候一些业务指标的初始化工作");
    }

    /**
     * 当前Bean注入到容器之后，再注入这个额外的Bean
     * @return
     */
    @Bean
    public Map<String, String> cacheMap() {
        System.out.println("通过@Bean生成的单例Bean");
        return new HashMap<>();
    }
}
